package com.rain.rainspringboot3.encryption.util;


import com.rain.rainspringboot3.encryption.annotation.EncryptField;
import com.rain.rainspringboot3.encryption.service.EncryptionService;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.util.*;

/**
 * 批量解密工具类
 * 优化批量数据解密性能，减少数据库和缓存访问次数
 */
@Component
public class BatchDecryptionHelper {
    
    /**
     * 批量解密方法
     */
    public static <T> void batchDecrypt(List<T> list, EncryptionService encryptionService) {
        if (list == null || list.isEmpty()) {
            return;
        }
        
        // 1. 收集所有需要解密的敏感数据ID
        Set<Long> sensitiveDataIds = new HashSet<>();
        Map<Long, List<FieldTarget>> idToTargetsMap = new HashMap<>();
        
        for (T item : list) {
            collectSensitiveDataIds(item, sensitiveDataIds, idToTargetsMap);
        }
        
        // 2. 批量解密
        if (!sensitiveDataIds.isEmpty()) {
            Map<Long, String> decryptedDataMap = encryptionService.batchDecryptFields(sensitiveDataIds);
            
            // 3. 将解密后的数据设置回对象
            applyDecryptedData(list, idToTargetsMap, decryptedDataMap);
        }
    }
    
    /**
     * 收集敏感数据ID
     */
    private static <T> void collectSensitiveDataIds(T item, Set<Long> sensitiveDataIds, 
                                                   Map<Long, List<FieldTarget>> idToTargetsMap) {
        Class<?> clazz = item.getClass();
        for (Field field : clazz.getDeclaredFields()) {
            if (field.isAnnotationPresent(EncryptField.class)) {
                try {
                    field.setAccessible(true);
                    Object value = field.get(item);
                    if (value != null && value instanceof Long) {
                        Long sensitiveDataId = (Long) value;
                        sensitiveDataIds.add(sensitiveDataId);
                        
                        // 记录ID和字段目标的映射关系
                        FieldTarget target = new FieldTarget(item, field);
                        idToTargetsMap.computeIfAbsent(sensitiveDataId, k -> new ArrayList<>()).add(target);
                    }
                } catch (Exception e) {
                    // 记录日志，继续处理其他字段
                }
            }
        }
    }
    
    /**
     * 应用解密后的数据
     */
    private static <T> void applyDecryptedData(List<T> list, 
                                              Map<Long, List<FieldTarget>> idToTargetsMap,
                                              Map<Long, String> decryptedDataMap) {
        for (Map.Entry<Long, List<FieldTarget>> entry : idToTargetsMap.entrySet()) {
            Long sensitiveDataId = entry.getKey();
            List<FieldTarget> targets = entry.getValue();
            String decryptedText = decryptedDataMap.get(sensitiveDataId);
            
            if (decryptedText != null) {
                for (FieldTarget target : targets) {
                    try {
                        target.field.setAccessible(true);
                        target.field.set(target.object, decryptedText);
                    } catch (Exception e) {
                        // 记录日志，继续处理其他字段
                    }
                }
            }
        }
    }
    
    /**
     * 字段目标内部类
     */
    private static class FieldTarget {
        Object object;
        Field field;
        
        FieldTarget(Object object, Field field) {
            this.object = object;
            this.field = field;
        }
    }
}